#include "binarystreamwriter.h"
#ifndef _WIN32
#include <arpa/inet.h>
#else
#include <Winsock2.h>
#pragma comment(lib, "Ws2_32.a")
#endif


//计算校验和
    unsigned short checksum(const unsigned short* buffer, int size)
    {
        unsigned int cksum = 0;
        while (size > 1)
        {
            cksum += *buffer++;
            size -= sizeof(unsigned short);
        }
        if (size)
        {
            cksum += *(unsigned char*)buffer;
        }
        //将32位数转换成16
        while (cksum >> 16)
            cksum = (cksum >> 16) + (cksum & 0xffff);

        return (unsigned short)(~cksum);
    }

    //将一个4字节的整型数值压缩成1~5个字节
    void write7BitEncoded(uint32_t value, std::string& buf)
    {
        do
        {
            unsigned char c = (unsigned char)(value & 0x7F);
            value >>= 7;
            if (value)
                c |= 0x80;

            buf.append(1, c);
        } while (value);
    }

    //将一个8字节的整型值编码成1~10个字节
    void write7BitEncoded(uint64_t value, std::string& buf)
    {
        do
        {
            unsigned char c = (unsigned char)(value & 0x7F);
            value >>= 7;
            if (value)
                c |= 0x80;

            buf.append(1, c);
        } while (value);
    }

//    //将一个1~5个字节的字符数组值还原成4字节的整型值
//    void read7BitEncoded(const char* buf, uint32_t len, uint32_t& value)
//    {
//        char c;
//        value = 0;
//        int bitCount = 0;
//        int index = 0;
//        do
//        {
//            c = buf[index];
//            uint32_t x = (c & 0x7F);
//            x <<= bitCount;
//            value += x;
//            bitCount += 7;
//            ++index;
//        } while (c & 0x80);
//    }

//    //将一个1~10个字节的值还原成4字节的整型值
//    void read7BitEncoded(const char* buf, uint32_t len, uint64_t& value)
//    {
//        char c;
//        value = 0;
//        int bitCount = 0;
//        int index = 0;
//        do
//        {
//            c = buf[index];
//            uint64_t x = (c & 0x7F);
//            x <<= bitCount;
//            value += x;
//            bitCount += 7;
//            ++index;
//        } while (c & 0x80);
//    }

net::BinaryStreamWriter::BinaryStreamWriter(std::string* data)
    :m_data(data)
{
    m_data->clear();
    m_data->clear();
    char str[BINARY_PACKLEN_LEN_2 + CHECKSUM_LEN];
    m_data->append(str, sizeof(str));
}

bool net::BinaryStreamWriter::WriteCString(const char* str, size_t len)
    {
        std::string buf;
        write7BitEncoded(len, buf);

        m_data->append(buf);

        m_data->append(str, len);

        //unsigned int ulen = htonl(len);
        //m_data->append((char*)&ulen,sizeof(ulen));
        //m_data->append(str,len);
        return true;
    }
    bool net::BinaryStreamWriter::WriteString(const std::string& str)
    {
        return WriteCString(str.c_str(), str.length());
    }
    const char* net::BinaryStreamWriter::GetData() const
    {
        return m_data->data();
    }
    size_t net::BinaryStreamWriter::GetSize() const
    {
        return m_data->length();
    }
    bool net::BinaryStreamWriter::WriteInt32(int32_t i, bool isNULL)
    {
        int32_t i2 = 999999999;
        if (isNULL == false)
            i2 = htonl(i);
        m_data->append((char*)& i2, sizeof(i2));
        return true;
    }
    bool net::BinaryStreamWriter::WriteInt64(int64_t value, bool isNULL)
    {
        char int64str[128];
        if (isNULL == false)
        {
#ifndef _WIN32
            sprintf(int64str, "%ld", value);
#else
            sprintf(int64str, "%lld", value);
#endif
            WriteCString(int64str, strlen(int64str));
        }
        else
            WriteCString(int64str, 0);
        return true;
    }
    bool net::BinaryStreamWriter::WriteShort(short i, bool isNULL)
    {
        short i2 = 0;
        if (isNULL == false)
            i2 = htons(i);
        m_data->append((char*)& i2, sizeof(i2));
        return true;
    }
    bool net::BinaryStreamWriter::WriteChar(char c, bool isNULL)
    {
        char c2 = 0;
        if (isNULL == false)
            c2 = c;
        (*m_data) += c2;
        return true;
    }
    bool net::BinaryStreamWriter::WriteDouble(double value, bool isNULL)
    {
        char   doublestr[128];
        if (isNULL == false)
        {
            sprintf(doublestr, "%f", value);
            WriteCString(doublestr, strlen(doublestr));
        }
        else
            WriteCString(doublestr, 0);
        return true;
    }
    void net::BinaryStreamWriter::Flush()
    {
        char* ptr = &(*m_data)[0];
        unsigned int ulen = htonl(m_data->length());
        memcpy(ptr, &ulen, sizeof(ulen));
    }
    void net::BinaryStreamWriter::Clear()
    {
        m_data->clear();
        char str[BINARY_PACKLEN_LEN_2 + CHECKSUM_LEN];
        m_data->append(str, sizeof(str));
    }
